﻿#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Text;
using MailQ.API;
using MailQ.MailSender.Properties;

#endregion

namespace MailQ.MailSender
{
	internal class MailSender
	{
		private static void Main(string[] Args)
		{
			if (Args.Length == 0)
			{
				PrintUsageInstruction(true);
				return;
			}
			switch (Args[0].ToLower().Trim())
			{
				case "/send":
					SendEmail();
					break;
				case "/set":
					SetSettings(Args);
					break;
				case "/get":
					PrintCurrentSettings();
					break;
				case "/help":
				case "/?":
					PrintUsageInstruction(false);
					break;
				default:
					PrintUsageInstruction(true);
					break;
			}
		}

		private static void PrintCurrentSettings()
		{
			StringBuilder Sb = new StringBuilder(0);
			Sb.Append("\r\nCurrent Settings:\r\n");
			Sb.Append(string.Format("  UserName -- {0}\r\n", Settings.Default.UserName));
			Sb.Append(string.Format("  Password -- {0}\r\n", Settings.Default.Password));
			Sb.Append(string.Format("  SmtpServer -- {0}\r\n", Settings.Default.SmtpServer));
			Sb.Append(string.Format("  SmtpPort -- {0}\r\n", Settings.Default.SmtpPort));
			Sb.Append(string.Format("  UseDefaultCredentials -- {0}\r\n", Settings.Default.UseDefaultCredentials));
			Sb.Append(string.Format("  UseSSL -- {0}\r\n", Settings.Default.UseSSL));
			Sb.Append(string.Format("  BccAddress -- {0}\r\n", Settings.Default.BccAddress));
			Sb.Append(string.Format("  TrackingMessage -- {0}\r\n", Settings.Default.TrackMessage));
			Console.WriteLine(Sb.ToString());
		}

		private static void PrintUsageInstruction(bool ShowError)
		{
			StringBuilder Sb = new StringBuilder(0);
			if (ShowError)
			{
				Sb.Append("\r\nWrong syntax! See usage options below.\r\n");
			}
			Sb.Append("\r\nUsage: \r\n");
			Sb.Append("  MailQ.MailSender.exe /help  --  Displays this help screen\r\n");
			Sb.Append("  MailQ.MailSender.exe /?     --  Displays this help screen\r\n");
			Sb.Append("  MailQ.MailSender.exe /send  --  Perform task of sending emails\r\n");
			Sb.Append("  MailQ.MailSender.exe /set -[setting:value]  -- set a new value for a setting\r\n");
			Sb.Append("  MailQ.MailSender.exe /get   --  Print a list of current settings with values\r\n");
			Sb.Append("  MailQ.MailSender.exe /set -SmtpPort:25 -SmtpServer:127.0.0.1\r\n");
			Sb.Append("\r\n");
			Sb.Append(".oO END Oo.");
			Console.WriteLine(Sb.ToString());
		}

		private static void SetSettings(ICollection<string> Args)
		{
			if (Args.Count < 2)
			{
				return;
			}
			foreach(string[] KeyVal in from Str in Args
			                           where (Str.StartsWith("-"))
			                           select Str.TrimStart('-').Split(':'))
			{
				SaveSetting(KeyVal[0], KeyVal[1]);
			}
		}

		private static void SaveSetting(string SettingName, object SettingValue)
		{
			switch (SettingName.ToLower())
			{
				case "smtpserver":
					Settings.Default.SmtpServer = SettingValue.ToString();
					break;
				case "smtpport":
					Settings.Default.SmtpPort = int.Parse(SettingValue.ToString());
					break;
				case "username":
					Settings.Default.UserName = SettingValue.ToString();
					break;
				case "password":
					Settings.Default.Password = SettingValue.ToString();
					break;
				case "usessl":
					Settings.Default.UseSSL = bool.Parse(SettingValue.ToString());
					break;
				case "usedefaultcredentials":
					Settings.Default.UseDefaultCredentials = bool.Parse(SettingValue.ToString());
					break;
				case "bccaddress":
					Settings.Default.BccAddress = SettingValue.ToString();
					break;
				case "trackmessage":
					Settings.Default.TrackMessage = SettingValue.ToString();
					break;
				case "sendingwait":
					Settings.Default.SendingWait = int.Parse(SettingValue.ToString());
					break;
				case "failedwait":
					Settings.Default.FailedWait = int.Parse(SettingValue.ToString());
					break;
				default:
					break;
			}
			Settings.Default.Save();
		}

		private static void SendEmail()
		{
			Console.WriteLine("MailQ is attempting to send mail...");

			Dictionary<int, MailMessage> FailedMessages = new Dictionary<int, MailMessage>(0);
			Dictionary<int, MailMessage> SentMessages = new Dictionary<int, MailMessage>(0);

			foreach (KeyValuePair<int, MailMessage> Message in EmailHelper.GetEmailsToSend(Settings.Default.SendingWait, Settings.Default.FailedWait))
			{
				MailQException Ex = new MailQException();
				if (EmailHelper.Send(Message.Value, ref Ex, Message.Key, Settings.Default.UserName, Settings.Default.Password,
									Settings.Default.SmtpServer, Settings.Default.SmtpPort, Settings.Default.UseDefaultCredentials,
									Settings.Default.UseSSL, Settings.Default.BccAddress, Settings.Default.TrackMessage))
				{
					SentMessages.Add(Message.Key, Message.Value);
					Console.WriteLine(string.Format("Message {0} has been sent to {1}", Message.Key, Message.Value.To));
					EmailHelper.AddToLog(
						string.Format("Message {0} has been sent to {1}", Message.Key, Message.Value.To), Message.Key);
				}
				else
				{
					FailedMessages.Add(Message.Key, Message.Value);
					Console.WriteLine(string.Format("Message {0} failed. Would've sent to {1}. Reason: {2} {3}",
													Message.Key, Message.Value.To, Ex.Message,
													Ex.InnerException != null
														? string.Format("-- {0}", Ex.InnerException.Message)
														: string.Empty));
					EmailHelper.AddToLog(string.Format("Message {0} failed. Would've sent to {1}. Reason: {2} {3}",
													   Message.Key, Message.Value.To, Ex.Message,
													   Ex.InnerException != null
														? string.Format("-- {0}", Ex.InnerException.Message)
														: string.Empty), Message.Key);
				}
			}

			EmailHelper.UpdateFailedMessages(FailedMessages);
			EmailHelper.UpdateSentMessages(SentMessages);
		}
	}
}